#ifndef __GTP_H__
#define __GTP_H__

#include "types.h"
#include "pk_buff.h"

//#define  __GTP_DEBUG__
#ifdef   __GTP_DEBUG__
#define  GTP_DEBUG(fmt,...)\
    do {fprintf(stderr, "[%s:%d] " fmt, __FILE__, __LINE__, ##__VA_ARGS__);} while(0)
#else
#define  GTP_DEBUG(fmt,...)  do{}while(0)
#endif

#define GTPv0_PORT  3386
#define GTPv1C_PORT 2123    /* 3G Control PDU */
#define GTPv1U_PORT 2152    /* 3G T-PDU */

extern u16 gtpc_port;
extern u16 gtpu_port;

/*-------------------------------------------------------------------------------*/
/* definitions of GTP messages */
#define GTP_MSG_UNKNOWN             0x00
#define GTP_MSG_ECHO_REQ            0x01
#define GTP_MSG_ECHO_RESP           0x02
#define GTP_MSG_VER_NOT_SUPP        0x03
#define GTP_MSG_NODE_ALIVE_REQ      0x04
#define GTP_MSG_NODE_ALIVE_RESP     0x05
#define GTP_MSG_REDIR_REQ           0x06
#define GTP_MSG_REDIR_RESP          0x07
#define GTP_MSG_CREATE_PDP_REQ      0x10
#define GTP_MSG_CREATE_PDP_RESP     0x11
#define GTP_MSG_UPDATE_PDP_REQ      0x12
#define GTP_MSG_UPDATE_PDP_RESP     0x13
#define GTP_MSG_DELETE_PDP_REQ      0x14
#define GTP_MSG_DELETE_PDP_RESP     0x15
#define GTP_MSG_CREATE_AA_PDP_REQ   0x16    /* 2G */
#define GTP_MSG_CREATE_AA_PDP_RESP  0x17    /* 2G */
#define GTP_MSG_DELETE_AA_PDP_REQ   0x18    /* 2G */
#define GTP_MSG_DELETE_AA_PDP_RESP  0x19    /* 2G */
#define GTP_MSG_ERR_IND             0x1A
#define GTP_MSG_PDU_NOTIFY_REQ      0x1B
#define GTP_MSG_PDU_NOTIFY_RESP     0x1C
#define GTP_MSG_PDU_NOTIFY_REJ_REQ  0x1D
#define GTP_MSG_PDU_NOTIFY_REJ_RESP 0x1E
#define GTP_MSG_SUPP_EXT_HDR        0x1F
#define GTP_MSG_SEND_ROUT_INFO_REQ  0x20
#define GTP_MSG_SEND_ROUT_INFO_RESP 0x21
#define GTP_MSG_FAIL_REP_REQ        0x22
#define GTP_MSG_FAIL_REP_RESP       0x23
#define GTP_MSG_MS_PRESENT_REQ      0x24
#define GTP_MSG_MS_PRESENT_RESP     0x25
#define GTP_MSG_IDENT_REQ           0x30
#define GTP_MSG_IDENT_RESP          0x31
#define GTP_MSG_SGSN_CNTXT_REQ      0x32
#define GTP_MSG_SGSN_CNTXT_RESP     0x33
#define GTP_MSG_SGSN_CNTXT_ACK      0x34
#define GTP_MSG_FORW_RELOC_REQ      0x35
#define GTP_MSG_FORW_RELOC_RESP     0x36
#define GTP_MSG_FORW_RELOC_COMP     0x37
#define GTP_MSG_RELOC_CANCEL_REQ    0x38
#define GTP_MSG_RELOC_CANCEL_RESP   0x39
#define GTP_MSG_FORW_SRNS_CNTXT     0x3A
#define GTP_MSG_FORW_RELOC_ACK      0x3B
#define GTP_MSG_FORW_SRNS_CNTXT_ACK 0x3C


#define GTP_MSG_RAN_INFO_RELAY      70
#define GTP_MBMS_NOTIFY_REQ         96
#define GTP_MBMS_NOTIFY_RES         97
#define GTP_MBMS_NOTIFY_REJ_REQ     98
#define GTP_MBMS_NOTIFY_REJ_RES     99
#define GTP_CREATE_MBMS_CNTXT_REQ   100
#define GTP_CREATE_MBMS_CNTXT_RES   101
#define GTP_UPD_MBMS_CNTXT_REQ      102
#define GTP_UPD_MBMS_CNTXT_RES      103
#define GTP_DEL_MBMS_CNTXT_REQ      104
#define GTP_DEL_MBMS_CNTXT_RES      105
#define GTP_MBMS_REG_REQ            112
#define GTP_MBMS_REG_RES            113
#define GTP_MBMS_DE_REG_REQ         114
#define GTP_MBMS_DE_REG_RES         115
#define GTP_MBMS_SES_START_REQ      116
#define GTP_MBMS_SES_START_RES      117
#define GTP_MBMS_SES_STOP_REQ       118
#define GTP_MBMS_SES_STOP_RES       119
#define GTP_MBMS_SES_UPD_REQ        120
#define GTP_MBMS_SES_UPD_RES        121
/* 122-127  For future use. Shall not be sent. 
 * If received, shall be treated as an Unknown message.
 */
#define GTP_MS_INFO_CNG_NOT_REQ     121
#define GTP_MS_INFO_CNG_NOT_RES     122
/* 130-239  For future use. Shall not be sent. 
 * If received, shall be treated as an Unknown message.
 */
#define GTP_MSG_DATA_TRANSF_REQ     0xF0
#define GTP_MSG_DATA_TRANSF_RESP    0xF1
/* 242-254  For future use. Shall not be sent. 
 * If received, shall be treated as an Unknown message.
 */
#define GTP_MSG_TPDU                0xFF


/*--------------------------------------------------------------------------------*/
/* definitions of fields in extension header */
#define GTP_EXT_CAUSE        0x01
#define GTP_EXT_IMSI        0x02
#define GTP_EXT_RAI            0x03
#define GTP_EXT_TLLI        0x04
#define GTP_EXT_PTMSI        0x05
#define GTP_EXT_QOS_GPRS    0x06
#define GTP_EXT_REORDER        0x08
#define GTP_EXT_AUTH_TRI    0x09
#define GTP_EXT_MAP_CAUSE    0x0B
#define GTP_EXT_PTMSI_SIG    0x0C
#define GTP_EXT_MS_VALID    0x0D
#define GTP_EXT_RECOVER        0x0E
#define GTP_EXT_SEL_MODE    0x0F

#define GTP_EXT_16            0x10
#define GTP_EXT_FLOW_LABEL    0x10
#define GTP_EXT_TEID        0x10    /* 0xFF10 3G */

#define GTP_EXT_17            0x11
#define GTP_EXT_FLOW_SIG    0x11
#define GTP_EXT_TEID_CP        0x11    /* 0xFF11 3G */

#define GTP_EXT_18            0x12
#define GTP_EXT_FLOW_II        0x12
#define GTP_EXT_TEID_II        0x12    /* 0xFF12 3G */

#define GTP_EXT_19            0x13
#define GTP_EXT_MS_REASON    0x13    /* same as 0x1D GTPv1_EXT_MS_REASON */
#define GTP_EXT_TEAR_IND    0x13    /* 0xFF13 3G */

#define GTP_EXT_NSAPI        0x14    /* 3G */
#define GTP_EXT_RANAP_CAUSE    0x15    /* 3G */
#define GTP_EXT_RAB_CNTXT    0x16    /* 3G */
#define GTP_EXT_RP_SMS        0x17    /* 3G */
#define GTP_EXT_RP            0x18    /* 3G */
#define GTP_EXT_PKT_FLOW_ID    0x19    /* 3G */
#define GTP_EXT_CHRG_CHAR    0x1A    /* 3G */
#define GTP_EXT_TRACE_REF    0x1B    /* 3G */
#define GTP_EXT_TRACE_TYPE    0x1C    /* 3G */
#define GTPv1_EXT_MS_REASON    0x1D    /* 3G */
#define GTP_EXT_TR_COMM        0x7E    /* charging */
#define GTP_EXT_CHRG_ID        0x7F
#define GTP_EXT_USER_ADDR    0x80
#define GTP_EXT_MM_CNTXT    0x81
#define GTP_EXT_PDP_CNTXT    0x82
#define GTP_EXT_APN            0x83
#define GTP_EXT_PROTO_CONF    0x84
#define GTP_EXT_GSN_ADDR    0x85
#define GTP_EXT_MSISDN        0x86
#define GTP_EXT_QOS_UMTS    0x87    /* 3G */
#define GTP_EXT_AUTH_QUI    0x88    /* 3G */
#define GTP_EXT_TFT            0x89    /* 3G */
#define GTP_EXT_TARGET_ID    0x8A    /* 3G */
#define GTP_EXT_UTRAN_CONT    0x8B    /* 3G */
#define GTP_EXT_RAB_SETUP    0x8C    /* 3G */
#define GTP_EXT_HDR_LIST    0x8D    /* 3G */
#define GTP_EXT_TRIGGER_ID    0x8E    /* 3G   142 7.7.41 */
#define GTP_EXT_OMC_ID        0x8F    /* 3G   143 TLV OMC Identity 7.7.42 */
#define GTP_EXT_RAN_TR_CONT            0x90    /* 3G   144 TLV RAN Transparent Container 7.7.43 */
#define GTP_EXT_PDP_CONT_PRIO        0x91    /* 3G   145 TLV PDP Context Prioritization 7.7.45 */
#define GTP_EXT_ADD_RAB_SETUP_INF    0x92    /* 3G   146 TLV Additional RAB Setup Information 7.7.45A */
#define GTP_EXT_SSGN_NO                0x93    /* 3G   147 TLV SGSN Number 7.7.47 */
#define GTP_EXT_COMMON_FLGS            0x94    /* 3G   148 TLV Common Flags 7.7.48 */
#define GTP_EXT_APN_RES                0x95    /* 3G   149 */
#define GTP_EXT_RA_PRIO_LCS            0x96    /* 3G   150 TLV Radio Priority LCS 7.7.25B */
#define GTP_EXT_RAT_TYPE            0x97    /* 3G   151 TLV RAT Type 7.7.50 */
#define GTP_EXT_USR_LOC_INF            0x98    /* 3G   152 TLV User Location Information 7.7.51 */
#define GTP_EXT_MS_TIME_ZONE        0x99    /* 3G   153 TLV MS Time Zone 7.7.52 */

#define GTP_EXT_IMEISV                0x9A    /* 3G */
#define GTP_EXT_CAMEL_CHG_INF_CON    0x9B    /* 3G   155 TLV CAMEL Charging Information Container 7.7.54 */
#define GTP_EXT_MBMS_UE_CTX            0x9C    /* 3G   156 TLV MBMS UE Context 7.7.55 */
#define GTP_EXT_TMGI                0x9D    /* 3G   157 TLV Temporary Mobile Group Identity (TMGI) 7.7.56 */
#define GTP_EXT_RIM_RA                0x9E    /* 3G   158 TLV RIM Routing Address 7.7.57 */
#define GTP_EXT_MBMS_PROT_CONF_OPT    0x9F    /* 3G   159 TLV MBMS Protocol Configuration Options 7.7.58 */
#define GTP_EXT_MBMS_SA                0xA0    /* 3G   160 TLV MBMS Service Area 7.7.60 */
#define GTP_EXT_SRC_RNC_PDP_CTX_INF 0xA1    /* 3G   161 TLV Source RNC PDCP context info 7.7.61 */
#define GTP_EXT_ADD_TRS_INF            0xA2    /* 3G   162 TLV Additional Trace Info 7.7.62 */
#define GTP_EXT_HOP_COUNT            0xA3    /* 3G   163 TLV Hop Counter 7.7.63 */
#define GTP_EXT_SEL_PLMN_ID            0xA4    /* 3G   164 TLV Selected PLMN ID 7.7.64 */
#define GTP_EXT_MBMS_SES_ID            0xA5    /* 3G   165 TLV MBMS Session Identifier 7.7.65 */
#define GTP_EXT_MBMS_2G_3G_IND        0xA6    /* 3G   166 TLV MBMS 2G/3G Indicator 7.7.66 */
#define GTP_EXT_ENH_NSAPI            0xA7    /* 3G   167 TLV Enhanced NSAPI 7.7.67 */
#define GTP_EXT_MBMS_SES_DUR        0xA8    /* 3G   168 TLV MBMS Session Duration 7.7.59 */
#define GTP_EXT_ADD_MBMS_TRS_INF    0xA9    /* 3G   169 TLV Additional MBMS Trace Info 7.7.68 */
#define GTP_EXT_MBMS_SES_ID_REP_NO    0xAA    /* 3G   170 TLV MBMS Session Identity Repetition Number 7.7.69 */
#define GTP_EXT_MBMS_TIME_TO_DATA_TR 0xAB    /* 3G   171 TLV MBMS Time To Data Transfer 7.7.70 */
#define GTP_EXT_PS_HO_REQ_CTX        0xAC    /* 3G   172 TLV PS Handover Request Context 7.7.71 */
#define GTP_EXT_BSS_CONT            0xAD    /* 3G   173 TLV BSS Container 7.7.72 */
#define GTP_EXT_CELL_ID                0xAE    /* 3G   174 TLV Cell Identification 7.7.73 */
#define GTP_EXT_PDU_NO                0xAF    /* 3G   175 TLV PDU Numbers 7.7.74 */
#define GTP_EXT_BSSGP_CAUSE            0xB0    /* 3G   176 TLV BSSGP Cause 7.7.75 */
#define GTP_EXT_REQ_MBMS_BEARER_CAP 0xB1    /* 3G   177 TLV Required MBMS bearer capabilities       7.7.76 */
#define GTP_EXT_RIM_ROUTING_ADDR_DISC 0xB2    /* 3G   178 TLV RIM Routing Address Discriminator       7.7.77 */
#define GTP_EXT_LIST_OF_SETUP_PFCS    0xB3    /* 3G   179 TLV List of set-up PFCs     7.7.78 */
#define GTP_EXT_PS_HANDOVER_XIP_PAR 0xB4    /* 3G   180 TLV PS Handover XID Parameters      7.7.79 */
#define GTP_EXT_MS_INF_CHG_REP_ACT    0xB5    /* 3G   181 TLV MS Info Change Reporting Action 7.7.80 */
#define GTP_EXT_DIRECT_TUNNEL_FLGS    0xB6    /* 3G   182 TLV Direct Tunnel Flags     7.7.81 */
#define GTP_EXT_CORRELATION_ID        0xB7    /* 3G   183 TLV Correlation-ID  7.7.82 */
#define GTP_EXT_BEARER_CONTROL_MODE 0xB8    /* 3G   184 TLV Bearer Control Mode     7.7.83 */
/* 239-250    Reserved for the GPRS charging protocol (see GTP' in 3GPP TS 32.295 [33])*/

#define GTP_EXT_C1            0xC1
#define GTP_EXT_C2            0xC2
#define GTP_EXT_REL_PACK    0xF9    /* charging */
#define GTP_EXT_CAN_PACK    0xFA    /* charging */
#define GTP_EXT_CHRG_ADDR    0xFB    /* 3G   251     TLV     Charging Gateway Address        7.7.44 */
/* 252-254    Reserved for the GPRS charging protocol (see GTP' in 3GPP TS 32.295 [33])*/
#define GTP_EXT_DATA_REQ    0xFC    /* charging */
#define GTP_EXT_DATA_RESP    0xFD    /* charging */
#define GTP_EXT_NODE_ADDR    0xFE    /* charging */
#define GTP_EXT_PRIV_EXT    0xFF

/*---------------------------------------------------------------------------------*/

#pragma pack(push)

#pragma pack(1)

struct gtphdr {
    u8  flag;
    u8  msg;
    u16 len;
};

#define GTPv0_HDR_LENGTH 20
#define GTPv1_HDR_LENGTH 12
#define GTP_PRIME_HDR_LENGTH 6

#define MAX_APN_LEN  102
#define IPV6_ENABLE 

struct ip6_addr {
    u8 bytes[16];        /* 128 bit IP6 address */
};

struct IPADDR {
    u32 len;
    union {
       u32 addr4;
       struct ip6_addr addr6; 
    };
};

#define IMEISV_STR_LEN  16
#define MSISDN_STR_LEN  13
#define IMSI_STR_LEN    15

struct imsi {
    u64  dig;
    char str[16];
};

struct msisdn {
    u64  dig;
    char str[16];
};

struct imei {
    u64  dig;
    char str[20];
};

struct QOS {
    u8 spare1;
    u8 delay;
    u8 reliability;
    u8 peak;
    u8 spare2;
    u8 precedence;
    u8 spare3;
    u8 mean;
};

struct UMTS_QOS {
    unsigned int mss;
    unsigned int mu;
    unsigned int md;
};

struct TEID_DATA2 {
    u8  nsapi;
    u32 teid_data2;
};

struct RAB_CNTXT {
    u8  nsapi;
    u8  pad0;
    u16 pad1;
    u16 rab_gtpu_dn;
    u16 rab_gtpu_up;
    u16 rab_pdu_dn;
    u16 rab_pdu_up;
};

struct FLOW_ID {
   u8  nsapi;
   u8  flow_id;
};

/*24*/
struct RD_PRI {
    u8 nsapi;
    u8 radio_priority;
};

struct PDP_CNTXT {
    u8 nsapi;
    u8 order;
    u8 asi;
    u8 vaa;
    u8 ea;
    u8 sapi;

    u16 sn_down;
    u16 sn_up;
    u8  pdu_send_no;
    u8  pdu_rec_no;

    u32 up_teid_control;
    u32 up_teid_data1;

    u8  pdp_type_org;
    struct IPADDR pdp_addr;
    struct IPADDR ggsn_addr_ctl;
    struct IPADDR ggsn_addr_data;

    u8 ggsn_addr_len_ctl;
    u8 ggsn_addr_len_data;
   
    char apn[32];
    u8 trans_id;
    u8 pdp_cntxt_id;
    u16 up_flow;
};

/* Geographic Location Type */
enum {
	LOC_TYPE_CGI = 0,
	LOC_TYPE_SAI = 1,
	LOC_TYPE_RAI = 2,
};  

struct RAI {
    u16  mcc;
    u16  mnc;
    u16  lac;
    u16  rac;
};

struct CGI {
    u16  mcc;
    u16  mnc;
    u16  lac;
    u16  ci;
};

struct SAI {
    u16  mcc;
    u16  mnc;
    u16  lac;
    u16  sac;
};

struct USR_LOC {
    u32  type;
    union {
        struct CGI cgi;
        struct SAI sai;
        struct RAI rai;
    };
};


struct MS_TMZ {
    u8 tm_zone;
    u8 daylight;
};

struct gtp_info {
    u32  gsn_addr_dst;
    u32  gsn_addr_src;
    u32  teid;
    u8   flag;
    u8   msg;
    u16  seq;
    u8   pdu_no;
    u8   exh_type;
    u16  payload_len;
    char  data[0];  
};

struct pdp_create_req {
    struct imsi   imsi;      /* conditional */
    struct msisdn msisdn;    /* conditional */
    struct imei   imeisv;    /* optional */
    u32 teid_data;    /* mandatory */
    u32 teid_cp;      /* conditional */
    u8  sel_mod;      /* conditional */
    u8  nsapi;        /* mandatory */
    u8  nsapi_link;   /* conditional */
    u8  rat_type;
    u16 proto_id;

	struct USR_LOC  location;

	struct RAI       rai;
	struct UMTS_QOS  umts_qos;
	struct QOS       gprs_qos;

    struct IPADDR usr_addr;       /* conditional */ 
    struct IPADDR gsn_addr_cp;    /* mandatory */ 
    struct IPADDR gsn_addr_data;  /* mandatory */ 
    char  apn[32];                /* conditional */
};

struct pdp_create_resp {
    u8  cause;                    /* mandatory */ 
    u8  nsapi;                    /* conditional */ 
    u16 pad;          
    u32 teid_data;                /* conditional */ 
    u32 teid_cp;                  /* conditional */ 
    u32 chrg_id;                  /* conditional */ 
    struct IPADDR  usr_addr;      /* conditional */ 
    struct IPADDR  gsn_addr_cp;   /* conditional */ 
    struct IPADDR  gsn_addr_data; /* conditional */ 
};


struct pdp_update_req {
    u64 imsi;      /* conditional */ 
    u32 teid_data; /* mandatory   */ 
    u32 teid_cp;   /* conditional */ 
    u8  nsapi;     /* mandatory   */ 
    u8  rat_type;
    u16 pad1;
    struct RAI  rai;
	struct USR_LOC  location; 		/*	guotie 2014-03-10		 */
	struct IPADDR gsn_addr_cp;        /* mandatory */ 
    struct IPADDR gsn_addr_data;      /* mandatory */ 
    struct IPADDR gsn_addr_cp_alt;    /* optional */ 
    struct IPADDR gsn_addr_data_alt;  /* optional */    
};

struct pdp_update_resp {
    u8  cause;
    u8  pad0;
    u16 pad1;
    u32 teid_data;
    u32 teid_cp;
    struct IPADDR  gsn_addr_cp;
    struct IPADDR  gsn_addr_data;
    struct IPADDR  gsn_addr_cp_alt;
    struct IPADDR  gsn_addr_data_alt;
};

struct pdp_delete_req {
    u8 tear_id; /* mandatory */
    u8 nsapi;   /* mandatory */
};

struct pdp_delete_resp {
    u8 cause;  /* mandatory */
    u8 pad;
};

#pragma pack(pop)


/*----------------------------------------*/
int decode_gtp_u(struct pk_buff *pkt);
int decode_gtp_c(struct pk_buff *pkt);
int gtp_opt_init();
void gtp_opt_clean();

#endif


